package org.cleverframe.fastdfs.pool;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;

public class FTPConnectionPool {

    private static final Logger logger = LoggerFactory.getLogger(FTPConnectionPool.class);
    private static final String SERVER = "10.10.180.176";
    private static final int PORT = 21;
    private static final String USERNAME = "ftp176";
    private static final String PASSWORD = "FTP176";


    private ArrayBlockingQueue<FTPClient> pool;
    private int maxSize;

    public FTPConnectionPool(int maxSize) {
        this.maxSize = maxSize;
        this.pool = new ArrayBlockingQueue<>(maxSize);
    }

    public FTPClient borrowObject() throws InterruptedException {
        FTPClient ftpClient = null;
        try {
            ftpClient = pool.poll(5, TimeUnit.SECONDS);
            if (ftpClient == null) {
                ftpClient = createNewFTPClient();
            } else if (!ftpClient.isConnected()) {
                pool.remove(ftpClient);
                ftpClient = createNewFTPClient();
            }else {
                int replyCode = ftpClient.getReplyCode();
                logger.info("ftpclient return code:{}",replyCode);
                if (!FTPReply.isPositiveCompletion(replyCode)) {
                    logger.info("尝试重连接开始......");
                    ftpClient = tryReconnected(ftpClient);
                }
            }
        }catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw e;
        }catch (Exception e){
            if (ftpClient != null) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioException) {
                    logger.error("Error disconnecting FTP client after exception", ioException);
                }
            }
        }
        return ftpClient;
    }




    private FTPClient tryReconnected( FTPClient ftpClient) {

        try {
            // 尝试重新连接
            ftpClient.connect(SERVER, PORT);
            ftpClient.login(USERNAME, PASSWORD);
            int replyCode = ftpClient.getReplyCode();
            logger.info("tryReconnected ftpclient return code:{}",replyCode);
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                throw new IOException("Failed to login to FTP server");
            }
            ftpClient.setRemoteVerificationEnabled(false);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.setControlKeepAliveTimeout(300);
            logger.info("Reconnected successfully");
        } catch (IOException e) {
            logger.error("Failed to reconnect FTP client", e);
            pool.remove(ftpClient);
            try {
                ftpClient.disconnect();
            } catch (IOException ex) {
                logger.error("Error disconnecting FTP client", ex);
            }
            ftpClient = createNewFTPClient();
        }
        return ftpClient;

    }

    public void returnObject(FTPClient ftpClient) {
        if (ftpClient != null && pool.size() < maxSize) {
//            resetFTPClient(ftpClient);
            pool.offer(ftpClient);
        } else {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void resetFTPClient(FTPClient ftpClient) {
        try {
            ftpClient.completePendingCommand();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
        } catch (IOException e) {
            logger.error("Error resetting FTP client", e);
        }
    }

    private FTPClient createNewFTPClient() {
        FTPClient ftpClient = new FTPClient();
        try {
//            ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));

            ftpClient.connect(SERVER, PORT);
            ftpClient.login(USERNAME, PASSWORD);
            ftpClient.setRemoteVerificationEnabled(false);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.setControlKeepAliveTimeout(300);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftpClient;
    }
}
